﻿#region Using Statements
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using QuickGraph;
using SharedCongkak;
using System.Linq;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;

using Path = SharedCongkak.Path;
#endregion

namespace Congkak
{

    public class BasicLevel: DrawableGameComponent, ILevel
    {
        

        AdjacencyGraph<AbstractHole, SharedCongkak.Path> level;
        List<SharedCongkak.Path> pathList = new List<SharedCongkak.Path>();
        AbstractHole highlightedHole;

        public event EventHandler OnHoleSelect;
        public event EventHandler<HoleEventArgs> OnSeedAddedToHole;

        ContentManager levelContent;

        private Vector2 Position
        {
            set;
            get;
        }

        public BasicLevel(Game game):this(game, Vector2.Zero)
        {

        }

        public BasicLevel(Game game, Vector2 position)
            : base(game)
        {
            Position = position;
            levelContent = new ContentManager(game.Services, "Content");
        }

        protected override void LoadContent()
        {
            SharedCongkak.Path.LoadContent(levelContent);
            //LevelData testData = levelContent.Load<LevelData>("LevelData/XNAlevel");
            LevelData testData = levelContent.Load<LevelData>("LevelData/Editorlevel");
            
            level = testData.ConvertToQuickGraph();
            //GameState gameState = Game.Services.GetService(typeof(GameState)) as GameState;
            foreach (var hole in level.Vertices)
            {
                hole.OnSeedAdded += (_sender, _args) => OnSeedAddedToHole(_sender, _args);
                hole.OnSelect += SelectHole;
                hole.OnEnter += HighlightHole;
                AddSeed(hole, 1);
            }
            highlightedHole = level.Vertices.Last<AbstractHole>();

            highlightedHole.Highlight = true;
            level.Vertices.ElementAt(0).PrevEdges[0].StartEffect();

        }

        private void AddSeed(AbstractHole hole, int numSeed)
        {
            for (int i = 0; i < numSeed; i++)
            {
                Seed seed = new Seed(Color.Red, 10);
                hole.AddSeed(seed);
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (var hole in level.Vertices)
            {
                hole.Draw(spriteBatch);
            }

            foreach (var path in level.Edges)
            {
                path.Draw(spriteBatch);
            }
        }

        public override void Update(GameTime gameTime)
        {
            foreach (SharedCongkak.Path path in level.Edges)
            {
                path.Update(gameTime);
            }
        }

        public void HighlightHole(Object hole, EventArgs eventArg)
        {
            highlightedHole.Highlight = false;
            highlightedHole = hole as AbstractHole;
            highlightedHole.Highlight = true;
        }

        private void SelectHole(Object hole, EventArgs eventArg)
        {
            OnHoleSelect(hole, eventArg);

        }
        public void HightlightNextHole()
        {
            var path = highlightedHole.NextEdges.LastOrDefault();
            if (path != null && path.Target is Hole && path.Target.IsHome)
                HighlightHole(path.Target, null);
        }

        public void HightlightPrevHole()
        {
            var path = highlightedHole.PrevEdges.LastOrDefault();
            if (path != null && path.Source is Hole && path.Source.IsHome)
                HighlightHole(path.Source, null);
        }

        public void Hover(int X, int Y)
        {
            foreach (var hole in level.Vertices)
            {             
                if (hole.MouseHover(X, Y))
                    break;

            }
        }

        public void Click(int X, int Y)
        {
            foreach (var hole in level.Vertices)
            {
                if (hole.CollisionRect.Contains(X, Y))
                {
                    hole.MouseClicked(X, Y);
                    break;
                }
            }
        }

        public bool IsValidMoves()
        {
            foreach (var hole in level.Vertices)
            {
                if (!hole.IsHome || (hole is Store))
                    continue;

                if (hole.NoOfSeeds > 0)
                    return true;                
            }

            return false;
        }

        public void Serialize(ContentManager content)
        {
            LevelData levelData = new LevelData();
            levelData.FromQuickGraph(level);
            using (XmlWriter write = XmlWriter.Create("XNALevel.xml"))
                IntermediateSerializer.Serialize<LevelData>(write, levelData, null);

            LevelData testData = content.Load<LevelData>("LevelData/XNAlevel");
            var testGraph = testData.ConvertToQuickGraph();            
        }

        protected override void UnloadContent()
        {
            levelContent.Unload();
        }

        public AbstractHole GetHole(Point position)
        {
            foreach (var hole in level.Vertices)
            {
                if (hole.ContainsPoint(position))
                {
                    return hole;
                }
            }
            return null;
        }

        public void RemovePath(Path path)
        {
            if (path == null) return;
            path.Source.NextEdges.Remove(path);
            path.Target.PrevEdges.Remove(path);
            level.RemoveEdge(path);
        }

        public void AddPath(AbstractHole source, AbstractHole target)
        {
            if (source == target || source == null || target == null)
                return;
            Path path = new Path(source, target);
            level.AddEdge(path);
        }

        public void AutoChooseHole()
        {
            var hole = (from h in level.Vertices.OfType<Hole>()
                        where h.IsHome == true
                        orderby h.NoOfSeeds
                        select h).LastOrDefault();
            if (hole != null)
                HighlightHole(hole, null);
                      
        }
    }
}
